﻿namespace Atomic.Plugins.Users.Data
{
    using System;
    using System.Text;
    using System.Linq;
    using System.Collections.Generic;
    using System.Data;
    using System.Data.SqlClient;

    using Atomic.Extensions;
    using Atomic.Collections;
    using Atomic.Data.AdoNet;
    using Atomic.Modules.Security;
    using Atomic.Plugins.Users.Models;
    using Atomic.Plugins.Users.Domain.Admin;

    /// <summary>
    /// 角色管理数据访问器接口。
    /// </summary>
    public class RoleAdminRepository : RepositoryBase, IRoleAdminRepository
    {
        /// <summary>
        /// 表名。
        /// </summary>
        private const string TABLE_NAME = "atomic_u_roles";

        /// <summary>
        /// 表主键。
        /// </summary>
        private const string TABLE_KEY = "Id";

        /// <summary>
        /// 判断角色名称是否存在。
        /// </summary>
        /// <param name="roleName">角色编号。</param>
        /// <returns>已存在则返回 true，否则返回 false。</returns>
        public bool ExistRoleId(int roleId)
        {
            return this.DataProvider.Exist(TABLE_NAME, TABLE_KEY, "Id = " + roleId);
        }

        /// <summary>
        /// 判断角色名称是否存在。
        /// </summary>
        /// <param name="roleName">角色名称。</param>
        /// <returns>已存在则返回 true，否则返回 false。</returns>
        public bool ExistRoleName(string roleName)
        {
            IDataParameter parameter = new SqlParameter("@name", SqlDbType.NVarChar, 50);

            parameter.Value = roleName;

            return this.DataProvider.Exist(TABLE_NAME, TABLE_KEY, "Name = @name", parameter);
        }

        /// <summary>
        /// 判断角色名称是否存在。
        /// </summary>
        /// <param name="roleName">角色编号。</param>
        /// <param name="roleName">角色名称。</param>
        /// <returns>已存在则返回 true，否则返回 false。</returns>
        public bool ExistRoleName(int roleId, string roleName)
        {
            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@id", SqlDbType.Int),
                        new SqlParameter("@name", SqlDbType.NVarChar, 50)
                    };

            parameters[0].Value = roleId;
            parameters[1].Value = roleName;

            return this.DataProvider.Exist(TABLE_NAME, TABLE_KEY, "Id <> @id AND Name = @name", parameters);
        }

        /// <summary>
        /// 增加角色。
        /// </summary>
        /// <param name="addRoleModel">增加角色模型。</param>
        /// <returns>操作成功返回 true，否则返回 false。</returns>
        public bool AddRole(AddRoleModel addRoleModel)
        {
            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@id", SqlDbType.Int),
                        new SqlParameter("@name", SqlDbType.NVarChar, 50),
                        new SqlParameter("@displayName", SqlDbType.NVarChar, 50),
                        new SqlParameter("@type", SqlDbType.Int)
                    };

            parameters[0].Value = addRoleModel.Id;
            parameters[1].Value = addRoleModel.Name;
            parameters[2].Value = addRoleModel.DisplayName;
            parameters[3].Value = (int)addRoleModel.Type;

            string sql = string.Format("INSERT INTO {0}(Id, Name, DisplayName, [Type], [Permissions]) VALUES (@id, @name, @displayName, @type, '')", TABLE_NAME);

            return this.DataProvider.ExecuteSqlCommand(sql, parameters) > 0;
        }

        /// <summary>
        /// 编辑角色。
        /// </summary>
        /// <param name="roleId">角色编号。</param>
        /// <param name="editRoleModel">增加角色模型。</param>
        /// <returns>操作成功返回 true，否则返回 false。</returns>
        public bool EditRole(int roleId, EditRoleModel editRoleModel)
        {
            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@id", SqlDbType.Int),
                        new SqlParameter("@name", SqlDbType.NVarChar, 50),
                        new SqlParameter("@displayName", SqlDbType.NVarChar, 50),
                        new SqlParameter("@type", SqlDbType.Int)
                    };

            parameters[0].Value = roleId;
            parameters[1].Value = editRoleModel.Name;
            parameters[2].Value = editRoleModel.DisplayName;
            parameters[3].Value = (int)editRoleModel.Type;

            string sql = string.Format("UPDATE {0} SET Name = @name, DisplayName = @displayName, Type = @type WHERE Id = @id", TABLE_NAME);

            return this.DataProvider.ExecuteSqlCommand(sql, parameters) > 0;
        }

        /// <summary>
        /// 授权角色。
        /// </summary>
        /// <param name="roleId">角色编号。</param>
        /// <param name="permissions">权限集合。</param>
        /// <returns>操作成功返回 true，否则返回 false。</returns>
        public bool RoleAuthorize(int roleId, IEnumerable<Permission> permissions)
        {
            StringBuilder permissionStrings = new StringBuilder();

            if (permissions != null && permissions.Count() > 0)
            {
                foreach (var permission in permissions)
                {
                    if (!permission.IsNull())
                    {
                        if (permissionStrings.Length > 0)
                        {
                            permissionStrings.Append(",");
                        }

                        permissionStrings.Append(permission.Id);
                    }
                }
            }

            IDataParameter[] parameters = 
                    { 
                        new SqlParameter("@id", SqlDbType.Int),
                        new SqlParameter("@permissions", SqlDbType.NVarChar, 1000)
                    };

            parameters[0].Value = roleId;
            parameters[1].Value = permissionStrings.ToString();

            string sql = string.Format("UPDATE {0} SET Permissions = @permissions WHERE Id = @id", TABLE_NAME);

            return this.DataProvider.ExecuteSqlCommand(sql, parameters) > 0;
        }

        /// <summary>
        /// 获得角色信息分页列表。
        /// </summary>
        /// <param name="pageIndex">页码。</param>
        /// <param name="pageSize">页大小。</param>
        /// <returns>角色信息分页列表。</returns>
        public IPageOfItems<ViewRole> GetRoles(int pageIndex, int pageSize)
        {
            string sqlWhere = string.Empty;

            var items = this.DataProvider.GetPage<ViewRole>(
                pageIndex,
                pageSize,
                TABLE_NAME,
                TABLE_KEY,
                "Id, Name, DisplayName, Type",
                sqlWhere,
                "DESC",
                0,
                this.GetRole);

            return new PageOfItems<ViewRole>(items, pageIndex, pageSize, this.DataProvider.GetCount(TABLE_NAME, sqlWhere));
        }

        /// <summary>
        /// 读取用户信息。
        /// </summary>
        /// <param name="dataReader">数据读取器。</param>
        /// <returns>用户信息。</returns>
        private ViewRole GetRole(IDataReader dataReader)
        {
            ViewRole role = new ViewRole();

            role.Id = dataReader.GetInt32(0);
            role.Name = dataReader.GetString(1);
            role.DisplayName = dataReader.GetString(2);
            role.Type = dataReader.GetInt32(3) == 1 ? "管理员" : "普通";

            return role;
        }
    }
}